/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.repository.utils;

import com.alibaba.druid.sql.ast.statement.SQLIfStatement;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.repository.DbParameter;
import com.inspur.edp.cef.api.repository.GspDbDataType;
import com.inspur.edp.cef.api.repository.ITypeTransProcesser;
import com.inspur.edp.cef.entity.condition.ExpressCompareType;
import com.inspur.edp.cef.entity.condition.ExpressRelationType;
import com.inspur.edp.cef.entity.condition.ExpressValueType;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.entity.condition.advanceconditions.BqlConditionValue;
import com.inspur.edp.cef.repository.adaptor.KeyWordsManager;
import com.inspur.edp.qdp.bql.api.IBqlExecuter;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.dataaccess.DbType;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.math.BigDecimal;
import java.sql.Connection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.inspur.edp.cef.api.repository.GspDbDataType.*;

public final class FilterUtil {
    public static String trans2DbRelation(ExpressRelationType relation) {
        switch (relation) {
            case And:
                return " AND ";
            case Or:
                return " OR ";
            case Empty:
                return "";
        }
        return "";
    }

    public static String buildCompareAndParam(FilterCondition filter, int number) {
        return buildCompareAndParam(filter, number, true);
    }

    public static String buildCompareAndParam(FilterCondition filter, int number, boolean userBindingParam) {
        String param = " ?" + (number) + " ";
        switch (filter.getCompare()) {
            case Equal:
                return " = " + param;
            case NotEqual:
                return "<>" + param;
            case Greater:
                return ">" + param;
            case GreaterOrEqual:
                return ">=" + param;
            case Less:
                return "<" + param;
            case LessOrEqual:
                return "<=" + param;
            case Like:
            case LikeStartWith:
            case LikeEndWith:
            case LikeIgnoreCase:
                return " like " + param;
            case NotLike:
            case NotLikeStartWith:
            case NotLikeEndWith:
                return " not like "+ param;
            case In:{
                userBindingParam = filter.getInValues() != null && filter.getInValues().size() >0 ? true : false;
                return userBindingParam? " IN"  + param : " IN";
            }
            case NotIn:{
                userBindingParam = filter.getInValues() != null && filter.getInValues().size() >0 ? true : false;
                return userBindingParam? " NOT IN"  + param : " NOT IN";
            }
            case Is:
                return " IS NULL";
            case IsNot:
                return " IS NOT NULL";
            default:
                return "";
        }
    }

    public static String parseExpression(String expression) {
        //TODO 表达式解析集成
        return ExpressionUtil.getExpressionValue(expression) + "";
    }

    public static List getBuildInCondition(String[] values, GspDbDataType dataType) {
        List list = null;
        if(dataType == Int){
            list = new ArrayList<Integer>();
        }
        else if(dataType == Decimal){
            list = new ArrayList<BigDecimal>();
        }
        else {
            list = new ArrayList<String>();
        }
        if(values == null || values.length ==0)
            return list;
        for(int i=0;i<values.length;i++){
            if(dataType == Int){
                list.add(Integer.parseInt(values[i].trim()));
            }
            else if(dataType == Decimal){
                list.add(new BigDecimal(values[i].trim()));
            }
            else {
                list.add(values[i]);
            }
        }
        return list;
    }

    public static String buildInCondition(String[] values, boolean isNum,String propName) {
        StringBuilder dataIdsCondition = new StringBuilder("(");
        if (values.length < 999) {
            for (int i = 0; i < values.length; i++) {

                if (i > 0) {
                    dataIdsCondition.append(",");
                }
                if (isNum) {
                    dataIdsCondition.append(values[i]);
                } else {
                    dataIdsCondition.append("'");
                    dataIdsCondition.append(values[i]);
                    dataIdsCondition.append("'");
                }
            }
            dataIdsCondition.append(")");
        } else {
            int groupCount = values.length / 999 + 1;
            int stratNum = 0;
            int endNum = 0;

            for (int i = 1; i <= groupCount; i++) {
                int searchCount;
                if (i == groupCount) {
                    searchCount = values.length - (i - 1) * 999;
                } else {
                    searchCount = 999;
                }

                if (searchCount == 0) {
                    continue;
                }
                if (i > 1) {
                    dataIdsCondition.append(" OR " + propName + " IN (");
                }

                endNum = endNum + searchCount;

                for (int j = stratNum; j < endNum; j++) {
                    if (j > stratNum) {
                        dataIdsCondition.append(",");
                    }
                    if (isNum) {
                        dataIdsCondition.append(values[j]);
                    } else {
                        dataIdsCondition.append("'");
                        dataIdsCondition.append(values[j]);
                        dataIdsCondition.append("'");
                    }
                }

                dataIdsCondition.append(")");

                stratNum = stratNum + searchCount;

            }
        }

        return String.valueOf(dataIdsCondition);
    }

    public static String buildInCondition(List values, boolean isNum,String propName) {
        StringBuilder dataIdsCondition = new StringBuilder("(");
        if (values.size() < 999) {
            for (int i = 0; i < values.size(); i++) {

                if (i > 0) {
                    dataIdsCondition.append(",");
                }
                if (isNum) {
                    dataIdsCondition.append(values.get(i));
                } else {
                    dataIdsCondition.append("'");
                    dataIdsCondition.append(values.get(i));
                    dataIdsCondition.append("'");
                }
            }
            dataIdsCondition.append(")");
        } else {
            int groupCount = values.size() / 999 + 1;
            int stratNum = 0;
            int endNum = 0;

            for (int i = 1; i <= groupCount; i++) {
                int searchCount;
                if (i == groupCount) {
                    searchCount = values.size() - (i - 1) * 999;
                } else {
                    searchCount = 999;
                }

                if (searchCount == 0) {
                    continue;
                }
                if (i > 1) {
                    dataIdsCondition.append(" OR " + propName + " IN (");
                }

                endNum = endNum + searchCount;

                for (int j = stratNum; j < endNum; j++) {
                    if (j > stratNum) {
                        dataIdsCondition.append(",");
                    }
                    if (isNum) {
                        dataIdsCondition.append(values.get(j));
                    } else {
                        dataIdsCondition.append("'");
                        dataIdsCondition.append(values.get(j));
                        dataIdsCondition.append("'");
                    }
                }

                dataIdsCondition.append(")");

                stratNum = stratNum + searchCount;

            }
        }

        return String.valueOf(dataIdsCondition);
    }

    public static void checkInParameterForSqlInjection(String value) {
        if (value == null || value.length() == 0) {
            return;
        }
        if (value.contains("'")) {
            throw new RuntimeException("无效的参数，参数值：" + value);
        }
    }

//    public stat

    public static List buildInCondition(FilterCondition filter, GspDbDataType dataType) {
        //todo ()这种写法得搞搞
        //直接传了('1','2','3')这种
        String[] values = null;
        if (filter.getValue().indexOf("(") == 0 && filter.getValue().lastIndexOf(")") == filter.getValue().length() - 1) {
            String innerValue = filter.getValue().substring(1, filter.getValue().length() - 1);
            values = innerValue.split(",");
            for(int i=0; i<values.length; i++){
                if(values[i].indexOf("'") == 0 && values[i].lastIndexOf("'") == values[i].length() -1 && values[i].length() >= 2){
                    values[i] = values[i].substring(1, values[i].length() -1);
                }
                values[i] = values[i].trim();
            }
        }
        else {
            String value = filter.getValue().trim();
            boolean isNum = dataType == Int || dataType == Decimal;
            if(isNum){
                //int类型的直接传递 1,2,3也支持一下
                values = value.indexOf("\r\n") > 0 ? value.split("\r\n") :value.split(",");
            }
            else {
                values = value.split("\r\n");
            }
        }
        List list = getBuildInCondition(values, dataType);
        return list;
    }

    public static String buildInCondition(FilterCondition filter, GspDbDataType dataType,String propName) {
        if (filter.getValue().indexOf("(") == 0 && filter.getValue().lastIndexOf(")") == filter.getValue().length() - 1) {
            return filter.getValue();
        }
        if (filter.getValue().toUpperCase().contains("SELECT")) {
            return "(" + filter.getValue() + ")";
        }
        String value = filter.getValue().trim();
        String[] values = value.split("\r\n");

        boolean isNum = dataType == Int || dataType == Decimal;
        return buildInCondition(values, isNum, propName);
    }

    //TODO parameters类型修改后，如何获取构造parameters的方法
    public static String parseFilterCondition(FilterCondition filter, String columnName, List<DbParameter> parameters, Connection db, GspDbDataType dataType
            , RefObject<Integer> paramNum, ITypeTransProcesser processer) {
        columnName = KeyWordsManager.getColumnAlias(columnName);
        if (filter.getExpresstype() == ExpressValueType.Expression && !filter.isParsed()) {
            filter.setValue(parseExpression(filter.getValue()));
            filter.setParsed(true);
        }

        if(filter.getExpresstype()==ExpressValueType.Bql)
        {
            if(filter.getCompare()==ExpressCompareType.In||filter.getCompare()==ExpressCompareType.NotIn)
            {
                if(filter.getCustomConditionValue()==null||(( filter
                    .getCustomConditionValue() instanceof BqlConditionValue))==false)
                    throw  new RuntimeException("bql定义不正确 。");
                BqlConditionValue bqlConditionValue= (BqlConditionValue) filter.getCustomConditionValue();
                String bqlString = getBqlExecutor().translateBql(bqlConditionValue.getBql(),bqlConditionValue.getRefBEIds());
                return String.format(" %1$s " + columnName + " %2$s (%3$s)  %4$s  %5$s",
                    filter.getLbracket(), buildCompareAndParam(filter, 0),
                    bqlString,filter.getRbracket(),
                    trans2DbRelation(filter.getRelation()));
            }
        }
        if (filter.getCompare() == ExpressCompareType.In || filter.getCompare() == ExpressCompareType.NotIn) {
            if(filter.getInValues() != null && filter.getInValues().size() > 0){
                return buildInFormat(filter, paramNum, parameters, dataType, columnName);
            }
            else {
                return String.format(" %1$s " + columnName + " %2$s%3$s  %4$s  %5$s",
                        filter.getLbracket(), buildCompareAndParam(filter, 0),
                        buildInCondition(filter, dataType,columnName), filter.getRbracket(),
                        trans2DbRelation(filter.getRelation()));
            }
        }

        if (filter.getCompare() == ExpressCompareType.Is || filter.getCompare() == ExpressCompareType.IsNot) {
            return String.format(" %1$s " + columnName + " %2$s %3$s %4$s", filter.getLbracket(),
                buildCompareAndParam(filter, 0), filter.getRbracket(), trans2DbRelation(filter.getRelation()));
        }

        Object value = processer.transType(filter, db);
        if (isLikeCondition(filter)) {
            String valueFormat = buildCompareAndParam(filter, paramNum.argvalue);
            //同时包含是否会有问题
            String filterValue = filter.getValue();
            valueFormat = filterValueZY(valueFormat, filterValue); //增加自定义转义符
            filterValue = filterZY(filterValue); //字符转义
            if(filter.getCompare() == ExpressCompareType.Like || filter.getCompare() == ExpressCompareType.NotLike){
                value = "%"+filterValue+"%";
            }
            else if(filter.getCompare() == ExpressCompareType.LikeStartWith || filter.getCompare() == ExpressCompareType.NotLikeStartWith){
                value = filterValue + "%";
            }
            else if(filter.getCompare() == ExpressCompareType.LikeEndWith || filter.getCompare() == ExpressCompareType.NotLikeEndWith){
                value = "%"+filterValue;
            }
            if(filter.getCompare()==ExpressCompareType.LikeIgnoreCase)
            {
                if(value==null||value instanceof String==false)
                    throw new RuntimeException("不支持的likeignorecase条件格式");
                value = "%"+filterValue.toLowerCase()+"%";
            }
            DbParameter paramItem = buildParam(filter.getFilterField() + paramNum.argvalue, dataType, value);
            parameters.add(paramItem);
            paramNum.argvalue++;
            if(filter.getCompare()==ExpressCompareType.LikeIgnoreCase)
                return String.format(" %1$s  lower(" + columnName + ")  %2$s %3$s %4$s", filter.getLbracket(), valueFormat, filter.getRbracket(), trans2DbRelation(filter.getRelation()));
                else
            return String.format(" %1$s " + columnName + " %2$s %3$s %4$s", filter.getLbracket(), valueFormat, filter.getRbracket(), trans2DbRelation(filter.getRelation()));
    }



        //region 06 TODO 这块逻辑需要调整，判断结构比较混乱
        StringBuilder conditionBuilder = new StringBuilder();
        if(CAFContext.current.getDbType()== DbType.Oracle ||CAFContext.current.getDbType()==DbType.DM){
            if(dataType==GspDbDataType.Clob){
                conditionBuilder.append(" ").append(filter.getLbracket()).append("to_char(").append("substr(").append(columnName).append(",0,4000))").append(" ").append(buildCompareAndParam(filter, paramNum.argvalue))
                        .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }
            else  if(filter.getCompare()==ExpressCompareType.LikeIgnoreCase)
            {
                conditionBuilder.append(" ").append(filter.getLbracket()).append("lower("+columnName).append(") ").append(buildCompareAndParam(filter, paramNum.argvalue))
                        .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }
            else{
                conditionBuilder.append(" ").append(filter.getLbracket()).append(columnName).append(" ").append(buildCompareAndParam(filter, paramNum.argvalue))
                        .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }

        }else if(CAFContext.current.getDbType()== DbType.SQLServer){
            if(dataType==GspDbDataType.Clob){
                conditionBuilder.append(" ").append(filter.getLbracket()).append("convert(").append("nvarchar(max)").append(",").append(columnName).append(")").append(" ").append(buildCompareAndParam(filter, ((Integer)paramNum.argvalue).intValue()))
                    .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));//处理SQL Sever数据库中的clob过滤
            }
            else  if(filter.getCompare()==ExpressCompareType.LikeIgnoreCase)
            {
                conditionBuilder.append(" ").append(filter.getLbracket()).append("lower("+columnName).append(") ").append(buildCompareAndParam(filter, paramNum.argvalue))
                        .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }
            else{
                conditionBuilder.append(" ").append(filter.getLbracket()).append(columnName).append(" ").append(buildCompareAndParam(filter, paramNum.argvalue))
                    .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }
        }
        else {
            if(filter.getCompare()==ExpressCompareType.LikeIgnoreCase)
            {
                conditionBuilder.append(" ").append(filter.getLbracket()).append("lower("+columnName).append(") ").append(buildCompareAndParam(filter, paramNum.argvalue))
                        .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
            }
                else
            conditionBuilder.append(" ").append(filter.getLbracket()).append(columnName).append(" ").append(buildCompareAndParam(filter, paramNum.argvalue))
                    .append(filter.getRbracket()).append(" ").append(trans2DbRelation(filter.getRelation()));
        }
        //endregion


        //IDbDataParameter paramItem = db.MakeInParam(filter.FilterField + paramNum, dataType, filter.Value.Length, value);
        if (filter.getCompare() == ExpressCompareType.Is || filter.getCompare() == ExpressCompareType.IsNot)
            return conditionBuilder.toString();
        DbParameter paramItem = buildParam(filter.getFilterField() + paramNum.argvalue, dataType, value);
        parameters.add(paramItem);
        paramNum.argvalue++;
        return conditionBuilder.toString();
    }
    /**
     * 筛选条件字符串%转义定义转义符
     * @param vaule
     * @return
     */
    private final static String filterValueZY(String vaule, String filterValue) {
        if (vaule == null) {
            return null;
        }
        List<String> replacestr = new ArrayList<>();
        boolean flag = false;
        replacestr.add("%");
        replacestr.add("\\");
        for(String replacechar: replacestr){
            if(needEscape(replacechar, filterValue)){
                flag = true;
                break;
            }
        }
        if (vaule.contains("like") && flag) {
            switch (CAFContext.current.getDbType()) {
                case SQLServer:
                    return vaule + " escape '!'";
                case Oracle:
                    return vaule + " escape '!'";
                case PgSQL:
                    return vaule + " escape '!'";
                case MySQL:
                    return vaule;
                case DM:
                    return vaule + " escape '!'";
                case HighGo:
                    return vaule + " escape '!'";
                case Gbase:
                    return vaule + " escape '!'";
                case Kingbase:
                    return vaule + " escape '!'";
                case Oscar:
                    return vaule + " escape '!'";
                case DB2:
                    return vaule + " escape '!'";
                case Unknown:
                    break;
            }
        }
        return vaule;
    }


    /**
     * 是否需要转义
     * @param escapceChar 转义字符
     * @param value 待检查字符串
     * @return
     */
    private static boolean needEscape(String escapceChar, String value){
        if(!value.contains(escapceChar))
            return false;

        List<String> commonEscapes = new ArrayList<>();
        commonEscapes.add("%");
        commonEscapes.add("\\");

        HashMap<String, List<String>> inCludes = new HashMap<>();
        HashMap<DbType, List<String>> exCludes = new HashMap<>();
        List<String> oraExcludes = new ArrayList<>();
        oraExcludes.add("\\");
        exCludes.put(DbType.Oracle, oraExcludes);

        //首先检查是否排除
        if(exCludes.containsKey(CAFContext.current.getDbType())){
            List<String> listExcludes = exCludes.get(CAFContext.current.getDbType());
            if(listExcludes != null && listExcludes.size() >0){
                if(listExcludes.contains(value))
                    return false;
            }
        }

        if(inCludes.containsKey(CAFContext.current.getDbType())){
            List<String> listIncludes = inCludes.get(CAFContext.current.getDbType());
            if(listIncludes != null && listIncludes.size() >0){
                if(listIncludes.contains(value))
                    return true;
            }
        }
        if(commonEscapes.contains(value)){
            return true;
        }
        return false;
    }

    /**
     * 筛选条件字符串%转义
     * @param beforeString
     * @return
     */
    private final static String filterZY(String beforeString) {
        if (beforeString == null) {
            return null;
        }
        List<String> replacestr = new ArrayList<>();
        replacestr.add("%");
        replacestr.add("\\");
        for (String replacechar : replacestr) {
            if (needEscape(replacechar, beforeString)) {
                switch (CAFContext.current.getDbType()) {
                    case SQLServer:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case Oracle:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case PgSQL:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case MySQL:
                        return beforeString.replace(replacechar, "\\" + replacechar);
                    case DM:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case HighGo:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case Gbase:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case Kingbase:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case Oscar:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case DB2:
                        beforeString = beforeString.replace(replacechar, "!" + replacechar);
                        break;
                    case Unknown:
                        break;
                }
            }
        }
        return beforeString;
    }

    private static String buildInFormat(FilterCondition filterCondition, RefObject<Integer> paramNum, List<DbParameter> parameters, GspDbDataType dataType, String columnName){
        int inSize = filterCondition.getInValues().size();
        int batchCount = 999;
        if(inSize <= batchCount){
            String inValueFormat = buildCompareAndParam(filterCondition, paramNum.argvalue);
            DbParameter paramItem = buildParam(filterCondition.getFilterField() + paramNum.argvalue, dataType, filterCondition.getInValues());
            parameters.add(paramItem);
            paramNum.argvalue++;
            return String.format(" %1$s " + columnName + " %2$s%3$s  %4$s  ",
                    filterCondition.getLbracket(), inValueFormat, filterCondition.getRbracket(), trans2DbRelation(filterCondition.getRelation()));
        }

        StringBuilder sbInFormat = new StringBuilder();
        int batchSize = inSize%batchCount == 0 ? inSize/batchCount: (inSize/batchCount + 1);
        String operator = filterCondition.getCompare() == ExpressCompareType.In ? "in" :" not in";
        sbInFormat.append(" (");
        for(int i=0; i < batchSize; i++){
            if(i==0){
                sbInFormat.append(String.format("%s %s (", columnName, operator));
            }
            else {
                sbInFormat.append(String.format(" or %s %s(", columnName, operator));
            }
            sbInFormat.append(String.format("?%s ", paramNum.argvalue));
            sbInFormat.append(") ");

            int fromIndex = i*batchCount;
            int toIndex = (i+1)*batchCount;
            toIndex = toIndex > filterCondition.getInValues().size() ? filterCondition.getInValues().size() : toIndex;
            if(inSize > 15000 && (dataType == VarChar || dataType == NVarChar || dataType == Char || dataType == NChar || dataType == Clob || dataType == NClob)){
                StringBuilder sbTemp = new StringBuilder();
                List tempList = filterCondition.getInValues().subList(fromIndex, toIndex);
                for(int i1=0; i1< tempList.size(); i1++){
                    if(i1 == 0){
                        sbTemp.append(String.format("'%1$s'", tempList.get(i1)));
                    }
                    else {
                        sbTemp.append(String.format(",'%1$s'", tempList.get(i1)));
                    }
                }
                DbParameter paramItem = buildParam(filterCondition.getFilterField() + paramNum.argvalue, dataType, sbTemp.toString());
                parameters.add(paramItem);
                paramNum.argvalue++;
            }
            else{
                DbParameter paramItem = buildParam(filterCondition.getFilterField() + paramNum.argvalue, dataType, filterCondition.getInValues().subList(fromIndex, toIndex));
                parameters.add(paramItem);
                paramNum.argvalue++;
            }
        }
        sbInFormat.append(") ");
        return String.format(" %1$s %2$s%3$s  %4$s  ",
                filterCondition.getLbracket(), sbInFormat.toString(), filterCondition.getRbracket(), trans2DbRelation(filterCondition.getRelation()));
    }

    /**
     * 是否like条件
     * @param filter
     * @return
     */
    private static boolean isLikeCondition(FilterCondition filter) {
        boolean result = false;
        result = filter.getCompare() == ExpressCompareType.Like || filter.getCompare() == ExpressCompareType.LikeStartWith
                || filter.getCompare() == ExpressCompareType.LikeEndWith
                || filter.getCompare() == ExpressCompareType.NotLikeStartWith
                || filter.getCompare() == ExpressCompareType.NotLikeEndWith
                || filter.getCompare() == ExpressCompareType.NotLike
                || filter.getCompare() == ExpressCompareType.LikeIgnoreCase;
        return result;
    }

    public String handleInfCondition(FilterCondition filter,RefObject<Integer> paramNum, List<DbParameter> parameters, Object value, String columnName, GspDbDataType dataType){
        String valueFormat = buildCompareAndParam(filter, paramNum.argvalue);
        if(filter.getCompare() == ExpressCompareType.Like || filter.getCompare() == ExpressCompareType.NotLike){
            value = "%"+value+"%";
        }
        else if(filter.getCompare() == ExpressCompareType.LikeStartWith || filter.getCompare() == ExpressCompareType.NotLikeStartWith){
            value = value + "%";
        }
        else if(filter.getCompare() == ExpressCompareType.LikeEndWith || filter.getCompare() == ExpressCompareType.NotLikeEndWith){
            value = "%"+value;
        }
        DbParameter paramItem = buildParam(filter.getFilterField() + paramNum.argvalue, dataType, value);
        parameters.add(paramItem);
        paramNum.argvalue++;
        return String.format(" %1$s " + columnName + " %2$s %3$s %4$s", filter.getLbracket(), valueFormat, filter.getRbracket(), trans2DbRelation(filter.getRelation()));
    }



    private static IBqlExecuter getBqlExecutor() {
        return SpringBeanUtils.getBean(IBqlExecuter.class);
    }

    //TODO 增加静态字典，记录字段对应的解析方法（model中是bool，DO是int的方法，model中是bool，DO是char的方法）
    private static String parseValue(Connection db, FilterCondition filter, GspDbDataType dataType) throws ParseException {
        switch (dataType) {
            case DateTime:
                return processDateTimeValue(filter.getValue());
            case VarChar:
            case NVarChar:
            case Char:
            case NChar:
            case Clob:
            case NClob:
                return processStringValue(filter);
            default:
                return filter.getValue();
        }

    }

    private static String processDateTimeValue(String value) throws ParseException {
        DateFormat format = new SimpleDateFormat("yyyyMMdd HHmmss");
        return format.parse(value).toString();
    }

    public static java.util.Date transDateTime(java.util.Date dateTime) {
        //TODO 根据国际化信息转换时间格式
        return dateTime;
    }


///#warning 这个地方需要完善
    public static String processStringValue(FilterCondition filter) {
        if("".equals(filter.getValue())&&
                (CAFContext.current.getDbType()==DbType.Oracle || CAFContext.current.getDbType() == DbType.Kingbase)){ //|| CAFContext.current.getDbType()==DbType.Oscar
            if(filter.getCompare()==ExpressCompareType.IsNot || filter.getCompare()==ExpressCompareType.NotEqual){
                filter.setCompare(ExpressCompareType.IsNot);
                filter.setValue("NUll");
            }else{
                filter.setCompare(ExpressCompareType.Is);
                filter.setValue("NULL");
            }
        }
        return filter.getValue();
    }

    public static DbParameter buildParam(String paramName, GspDbDataType dataType, Object paramValue) {
        paramName = KeyWordsManager.getColumnAlias(paramName);
        switch (dataType) {
            case Int:
            case Decimal:
            case DateTime:
            case Date:
            case Boolean:
            case Jsonb:
                return new DbParameter(paramName, dataType, paramValue);
            case Clob:
            case NClob:
            case Char:
            case NChar:
            case VarChar:
            case NVarChar:
                if(paramValue == null)
                    return new DbParameter(paramName, dataType, paramValue);
                if(paramValue instanceof List){
                    return new DbParameter(paramName, dataType, paramValue);
                }
                return new DbParameter(paramName, dataType, paramValue.toString());
            case Blob:

                byte[] byteAry = (byte[]) ((paramValue instanceof byte[]) ? paramValue : null);
                int length = 0;
                if (byteAry != null) {
                    length = byteAry.length;
                }
                Object value = byteAry;
                if (value == null) {
                    value = null;
                }
                return new DbParameter(paramName, dataType, value);
            //case GSPDbDataType.UnKnown:
            //case GSPDbDataType.Cursor:
            //case GSPDbDataType.Default:
            default:
                throw new UnsupportedOperationException("dataType");
        }
    }


}
